﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kipple
{
    public class KippleLib
    {

        private Stack<int> a = new Stack<int>();
        private Stack<int> b = new Stack<int>();
        private Stack<int> c = new Stack<int>();
        private Stack<int> d = new Stack<int>();
        private Stack<int> e = new Stack<int>();
        private Stack<int> f = new Stack<int>();
        private Stack<int> g = new Stack<int>();
        private Stack<int> h = new Stack<int>();
        private Stack<int> i = new Stack<int>();
        private Stack<int> j = new Stack<int>();
        private Stack<int> k = new Stack<int>();
        private Stack<int> l = new Stack<int>();
        private Stack<int> m = new Stack<int>();
        private Stack<int> n = new Stack<int>();
        private Stack<int> o = new Stack<int>();
        private Stack<int> p = new Stack<int>();
        private Stack<int> q = new Stack<int>();
        private Stack<int> r = new Stack<int>();
        private Stack<int> s = new Stack<int>();
        private Stack<int> t = new Stack<int>();
        private Stack<int> u = new Stack<int>();
        private Stack<int> v = new Stack<int>();
        private Stack<int> w = new Stack<int>();
        private Stack<int> x = new Stack<int>();
        private Stack<int> y = new Stack<int>();
        private Stack<int> z = new Stack<int>();
        private Stack<int> at = new Stack<int>();

        static private Dictionary<String, Stack<int>> stackNames = new Dictionary<string, Stack<int>>();        

        public void Initialize()
        {
            stackNames.Add("a", a);
            stackNames.Add("b", b);
            stackNames.Add("c", c);
            stackNames.Add("d", d);
            stackNames.Add("e", e);
            stackNames.Add("f", f);
            stackNames.Add("g", g);
            stackNames.Add("h", h);
            stackNames.Add("i", i);
            stackNames.Add("j", j);
            stackNames.Add("k", k);
            stackNames.Add("l", l);
            stackNames.Add("m", m);
            stackNames.Add("n", n);
            stackNames.Add("o", o);
            stackNames.Add("p", p);
            stackNames.Add("q", q);
            stackNames.Add("r", r);
            stackNames.Add("s", s);
            stackNames.Add("t", t);
            stackNames.Add("u", u);
            stackNames.Add("v", v);
            stackNames.Add("w", w);
            stackNames.Add("x", x);
            stackNames.Add("y", y);
            stackNames.Add("z", z);
            stackNames.Add("A", a);
            stackNames.Add("B", b);
            stackNames.Add("C", c);
            stackNames.Add("D", d);
            stackNames.Add("E", e);
            stackNames.Add("F", f);
            stackNames.Add("G", g);
            stackNames.Add("H", h);
            stackNames.Add("I", i);
            stackNames.Add("J", j);
            stackNames.Add("K", k);
            stackNames.Add("L", l);
            stackNames.Add("M", m);
            stackNames.Add("N", n);
            stackNames.Add("O", o);
            stackNames.Add("P", p);
            stackNames.Add("Q", q);
            stackNames.Add("R", r);
            stackNames.Add("S", s);
            stackNames.Add("T", t);
            stackNames.Add("U", u);
            stackNames.Add("V", v);
            stackNames.Add("W", w);
            stackNames.Add("X", x);
            stackNames.Add("Y", y);
            stackNames.Add("Z", z);
            stackNames.Add("@", at);

        }

        public void PushId(String id1, String id2)
        {
            Stack<int> stack1 = stackNames[id1];
            Stack<int> stack2 = stackNames[id2];

            if (id2.Equals("@"))
            {
                int num;
                bool neg = false;
                if (stack1.Count != 0)
                    num = stack1.Pop();
                else
                    num = 0;
                if (num < 0)
                {
                    num = num * -1;
                    neg = true;
                }

                Stack<int> aux = new Stack<int>();
                while (num > 0)
                {
                    aux.Push(num % 10);
                    num = num / 10;
                }
                if (aux.Count == 0)
                    aux.Push(0);
                if(neg)
                    stack2.Push('-');
                while (aux.Count != 0)
                    stack2.Push((char)(aux.Pop() + 48));

            }
            else
            {
                if(stack1.Count != 0) 
                    stack2.Push(stack1.Pop());
                else
                    stack2.Push((char) 0);
            }
        }

        public void PushInt(int num, String id1)
        {
            Stack<int> stack1 = stackNames[id1];

            stack1.Push(num);
        }

        public void OperateId(String id1, String id2, String op)
        {
            Stack<int> stack1 = stackNames[id1];
            Stack<int> stack2 = stackNames[id2];
            if (op.Equals("+"))
            {
                if (stack2.Count != 0 && stack1.Count != 0)
                    stack1.Push(stack1.Peek() + stack2.Pop());
                else if(stack1.Count != 0 && stack2.Count == 0)
                    stack1.Push(stack1.Peek() + 0);
                else if(stack2.Count != 0 && stack1.Count == 0)
                    stack1.Push(0 + stack2.Pop());
                else
                    stack1.Push(0);
            }
            if (op.Equals("-"))
            {
                if (stack2.Count != 0 && stack1.Count != 0)
                    stack1.Push(stack1.Peek() - stack2.Pop());
                else if (stack1.Count != 0 && stack2.Count == 0)
                    stack1.Push(stack1.Peek() - 0);
                else if (stack2.Count != 0 && stack1.Count == 0)
                    stack1.Push(0 - stack2.Pop());
                else
                    stack1.Push(0);
            }
                       
        }


        public void OperateInt(String id1, int num, String op)
        {
            Stack<int> stack1 = stackNames[id1];
            if (op.Equals("+"))
            {
                if (stack1.Count != 0)
                    stack1.Push(stack1.Peek() + num);
                else
                    stack1.Push(0 + num);
            }
            if (op.Equals("-"))
            {
                if (stack1.Count != 0)
                    stack1.Push(stack1.Peek() - num);
                else
                    stack1.Push(0 - num);
            }

        }

        public bool Empty(String id) 
        {
            Stack<int> stack = stackNames[id];
            if (stack.Count == 0)
                return true;
            else
                return false;
        }

        public void Clear(String id)
        {
            Stack<int> stack = stackNames[id];
            if(stack.Count != 0)
                if (stack.Peek() == 0)
                    stack.Clear();
        }

        public void PrintOutput(KippleLib kl){
            Stack<int> stack = stackNames["o"];
            while (!kl.Empty("o"))
                    Console.Write((char)stack.Pop());
        }
    }
}
